package com.newly.common.core.service.operLogger.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.newly.common.base.annotation.NewlyLog;
import com.newly.common.base.constants.AuthConstant;
import com.newly.common.base.entity.PageUtils;
import com.newly.common.base.entity.auth.ICurrentTenant;
import com.newly.common.base.entity.sys.operLogger.dto.OperLoggerDto;
import com.newly.common.base.entity.sys.operLogger.po.OperLoggerPo;
import com.newly.common.core.service.operLogger.api.IOperLoggerService;
import com.newly.common.core.utils.RequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @program: newly-parent
 * @remark:
 * @author: guan
 * @create: 2021-12-04 18:07
 */
@Slf4j
@Service
public class OperLoggerService extends AbstractOperLoggerService implements IOperLoggerService {

    @Autowired
    private RequestUtils requestUtils;


    @Override
    public boolean save(OperLoggerDto operLoggerDto) {
        return this.insert(operLoggerDto);
    }

    @Override
    public boolean save(ProceedingJoinPoint proceedingJoinPoint, int status) {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        NewlyLog newlyLog = methodSignature.getMethod().getAnnotation(NewlyLog.class);
        if (!newlyLog.isOpen()) return false;

        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();

        OperLoggerPo operLoggerPo = new OperLoggerPo();
        operLoggerPo.setIp(requestUtils.getIp());
        operLoggerPo.setBrowse(requestUtils.getBrowse());
        operLoggerPo.setOperSystem(requestUtils.getOperationSystem());
        operLoggerPo.setReqUrl(requestUtils.getReqUri());
        operLoggerPo.setReqMethod(requestUtils.getReqMethod());

        operLoggerPo.setAbilityCode(newlyLog.ability().getCode());
        operLoggerPo.setArgument(argsArrayToString(proceedingJoinPoint.getArgs()));
        operLoggerPo.setStatus(status);
        operLoggerPo.setUserId(currentTenant.getUserId());
        operLoggerPo.setCreateTime(DateUtil.date());
        operLoggerPo.setTitle(newlyLog.title());
        int insert = operLoggerMapper.insert(operLoggerPo);
        return insert > 0;
    }


    @Override
    public boolean modify(OperLoggerDto operLoggerDto) {
        return this.update(operLoggerDto);
    }

    @Override
    public PageUtils list(Integer offset, Integer limit, Integer abilityCode,
                          String fromTime, String toTime, String keyword) {
        LambdaQueryWrapper<OperLoggerPo> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(OperLoggerPo::getCreateTime);
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        if (!currentTenant.isDev()) {
            List<String> entityIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.TENANT);
            entityIds.remove(currentTenant.getUserId());
            wrapper.in(OperLoggerPo::getUserId, entityIds);
        }

        IPage<OperLoggerPo> iPage = new Page<>(offset, limit);
        // 操作
        if (!ObjectUtil.isEmpty(abilityCode)) {
            wrapper.eq(OperLoggerPo::getAbilityCode, abilityCode);
        }
        // 创建时间
        if (!StrUtil.isBlank(fromTime) && !StrUtil.isBlank(toTime)) {
            wrapper.between(OperLoggerPo::getCreateTime, fromTime, toTime);
        }
        // 关键字
        if (!StrUtil.isBlank(keyword)) {
            wrapper.like(OperLoggerPo::getRemark, keyword);
        }

        iPage = operLoggerMapper.selectPage(iPage, wrapper);
        return new PageUtils(iPage);
    }


    @Override
    public List<OperLoggerPo> getByIds(List<String> logIds) {
        return this.selectByIds(logIds);
    }

    @Override
    public boolean removeByIds(List<String> logIds) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        if (!currentTenant.isDev()) {
            List<OperLoggerPo> operLoggerPos = this.getByIds(logIds);
            if (ObjectUtil.isEmpty(operLoggerPos)) {
                return false;
            }
            List<String> tenantIds = this.parseTenantIds(operLoggerPos);
            currentTenant.assertIncludeEntities(AuthConstant.AuthEntityType.TENANT, tenantIds);
        }
        int ret = operLoggerMapper.deleteBatchIds(logIds);
        return ret > 0;
    }

    @Override
    public boolean removeAll() {
        int delete = operLoggerMapper.delete(null);
        return delete > 0;
    }

    @Override
    public boolean clear() {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        if (currentTenant.isDev()) {
            return removeAll();
        }

        List<String> entityIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.TENANT);
        if (ObjectUtil.isEmpty(entityIds)) return true;
        entityIds.remove(currentTenant.getUserId());

        LambdaQueryWrapper<OperLoggerPo> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(OperLoggerPo::getUserId, entityIds);
        int delete = operLoggerMapper.delete(wrapper);
        return delete > 0;
    }


}
